﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using SmallTune.Models;
using NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate.Cfg;
using System.IO;
using NHibernate.Tool.hbm2ddl;
using System.Windows.Input;
using System.Windows;
using NHibernate.Linq;

namespace SmallTune.Controllers
{
    public class PlaylistController : BaseController
    {
        private ObservableCollection<Song> _songs;

        public ObservableCollection<Song> songs
        {
            get
            {
                return _songs;
            }

            set
            {
                _songs = value;
            }
        }

        #region Commands
        #region addSongCommand
        private ICommand _addSongCommand;

        public ICommand addSongCommand
        {
            get
            {
                if (this._addSongCommand == null)
                    this._addSongCommand = new RelayCommand(p => this.AddSong(), () => this.CanAddSong());

                return this._addSongCommand;
            }
        }
        #endregion
        #region playSongCommand
        private ICommand _playSongCommand;

        public ICommand playSongCommand
        {
            get
            {
                if (this._playSongCommand == null)
                    this._playSongCommand = new RelayCommand(p => this.PlaySong(), () => this.CanPlaySong());

                return this._playSongCommand;
            }
        }
        #endregion
        #endregion

        public PlaylistController()
        {
            songs = new ObservableCollection<Song>();

            // create our NHibernate session factory
            //var sessionFactory = CreateSessionFactory();
            /*
            using (var session = sessionFactory.OpenSession())
            {
                // populate the database
                using (var transaction = session.BeginTransaction())
                {
                    var africa_song = new Song { title = "Africa" };
                    var other_song = new Song { title = "Other Song" };

                    var genre = new Genre { name = "Genre1" };
                    var genre2 = new Genre { name = "Genre2" };

                    var artist = new Artist { name = "Special Artist" };
                    
                    africa_song.AddGenre(genre);
                    other_song.AddGenre(genre);
                    other_song.AddGenre(genre2);

                    var playlist = new Playlist { name = "BasicPlaylist" };

                    var album = new Album { name = "All of Africa", yearOfRelease = 1986 };
                    album.AddGenre(genre);
                    album.AddGenre(genre2);
                    album.AddSong(africa_song);
                    album.AddSong(other_song);

                    artist.AddAlbum(album);

                    playlist.AddSong(other_song);
                    playlist.AddSong(africa_song);

                    session.Save(playlist);
                    //session.Save(artist);

                    transaction.Commit();
                }
            }*/
        
        }

        public static ISessionFactory CreateSessionFactory()
        {
            return Fluently.Configure()
              .Database(
                SQLiteConfiguration.Standard
                  .UsingFile((Application.Current as SmallTune.App).dbPath)
              )
              .Mappings(m =>
                m.FluentMappings.AddFromAssemblyOf<PlaylistController>())
              .BuildSessionFactory();
        }

        /// <summary>
        /// Adds a Song to the Database
        /// </summary>
        public void AddSong()
        {
            //Display Dialog
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.FileName = "Document"; // Default file name 
            dlg.DefaultExt = ".mp3"; // Default file extension 
            dlg.Filter = "Audio files |*.mp3;*.flac;*.wav"; // Filter files by extension 

            // Show open file dialog box 
            Nullable<bool> result = dlg.ShowDialog();

            // Process open file dialog box results 
            if (result == true)
            {
                // Open document 
                string filename = dlg.FileName;

                //Read the tags
                TagLib.Tag tags = ReadTags(filename);

                //Requesting a new connection
                var sessionFactory = CreateSessionFactory();

                using (var session = sessionFactory.OpenSession())
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        //Declare everything
                        Artist artist;
                        Song song;
                        Playlist playlist;
                        Album album;
                        Genre genre;

                        //Check for the artist
                        var artistResult = from p in session.Query<Artist>()
                                             where p.name == tags.FirstAlbumArtist
                                             select p;

                        if (artistResult == null || artistResult.SingleOrDefault() == null)
                        {
                            if (String.IsNullOrEmpty(tags.FirstAlbumArtist))
                            {
                                artist = new Artist { name = "Unkown" };
                            }
                            else
                            {
                                artist = new Artist { name = tags.FirstAlbumArtist };
                            }
                        }
                        else
                        {
                            artist = (Artist)artistResult.Single();
                        }


                        //Check the album
                        var albumResult = from p in session.Query<Album>()
                                           where p.name == tags.Album
                                           select p;

                        if (albumResult == null || albumResult.SingleOrDefault() == null)
                        {
                            if (String.IsNullOrEmpty(tags.Album))
                            {
                                album = new Album { name = "Unkown" };
                            }
                            else
                            {
                                album = new Album { name = tags.Album };
                            }
                        }
                        else
                        {
                            album = (Album)albumResult.Single();
                        }

                        //Check the album
                        var songResult = from p in session.Query<Song>()
                                          where p.title == tags.Title && p.listOfAlbums.Contains(album) && p.listOfArtists.Contains(artist) 
                                          select p;

                        session.SaveOrUpdate(album);
                        session.SaveOrUpdate(artist);

                        if (songResult == null || songResult.SingleOrDefault() == null)
                        {
                            if (String.IsNullOrEmpty(tags.Title))
                            {
                                song = new Song { title = "Unkown" };
                                song.path = filename;
                            }
                            else
                            {
                                song = new Song { title = tags.Title };
                                song.path = filename;
                            }
                        }
                        else
                        {
                            song = (Song)songResult.Single();
                        }


                        playlist = new Playlist { name = "Default" };
                        album.AddSong(song);
                        artist.AddAlbum(album);
                        song.AddArtist(artist);
                        playlist.AddSong(song);

                        session.SaveOrUpdate(playlist);
                        transaction.Commit();

                        songs.Add(song);

                    }
                }
            }


        }

        private TagLib.Tag ReadTags(string filename)
        {
            TagLib.File newSong = TagLib.File.Create(filename);

            TagLib.Tag tags = newSong.Tag;
            newSong.Dispose();
            return tags;

        }

        public bool CanAddSong()
        {
            return true;
        }

        /// <summary>
        /// Plays a song from the database
        /// </summary>
        public void PlaySong()
        {

        }

        public bool CanPlaySong()
        {
            return true;
        }

        public override void MessageNotification(string message, object args)
        {
            throw new NotImplementedException();
        }
    }
}
